package morenoapp.model.impl;

import java.awt.Point;
import morenoapp.model.data.MorenoRespondentFace;
import morenoapp.model.enums.MorenoSex;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import morenoapp.model.data.MorenoAnswerFace;
import morenoapp.model.data.MorenoAnswerItemFace;
import morenoapp.model.data.MorenoMeasureFace;
import morenoapp.model.data.MorenoMetricFilterFace;
import morenoapp.model.data.MorenoQuestionFace;
import morenoapp.util.MorenoUtil;

/**
 *
 * @author dmitry.mamonov
 */
class MorenoRespondentImpl extends MorenoModelObject implements Serializable, MorenoRespondentFace {
    private static final long serialVersionUID = 1L;
    protected String name = "";
    protected Map<MorenoQuestionFace, MorenoAnswerFace> answersMap = new HashMap<MorenoQuestionFace, MorenoAnswerFace>();
    protected MorenoSex sex = MorenoSex.UNKNOWN;
    protected Point graphPosition;
    protected boolean passedPoll = false;
    MorenoRespondentImpl(MorenoModelImpl model) {
        super(model);
    }

    /**
     * Позиция элемента в модели с 0.
     * @return
     */
    @Override
    public int getIndex() {
        return getModel().getRespondentsList().indexOf(this);
    }

    @Override
    public String getName() {
        return name != null ? name : "";
    }

    @Override
    public void setName(String name) {
        assert name != null;
        this.name = name;
        getModel().fireRespondentChanged(this);
    }

    @Override
    public MorenoSex getSex() {
        return sex;
    }

    @Override
    public void setSex(MorenoSex sex) {
        assert sex != null;
        this.sex = sex;
        getModel().fireRespondentChanged(this);
    }

    @Override
    public boolean isPassedPoll() {
        return passedPoll;
    }

    @Override
    public void setPassedPoll(boolean passedPoll) {
        this.passedPoll = passedPoll;
        getModel().fireRespondentChanged(this);
    }

    @Override
    public String toHtmlString() {
        return MorenoUtil.wrapTextWithColor(sex.getColor(), name);
    }

    /**
     * Сравнивает по имени таким образом что бы все пустые имена оказались в конце списка.
     * @inheritDoc
     */
    @Override
    public int compareTo(Object o) {
        MorenoRespondentImpl other = (MorenoRespondentImpl) o;
        if (this.getName().equals(other.getName())) {
            return 0;
        } else {
            if (this.getName().isEmpty()) {
                return 1;
            } else if (other.getName().isEmpty()) {
                return -1;
            } else {
                return this.getName().compareTo(other.getName());
            }
        }
    }

    @Override
    public String toString() {
        return getName();
    }

    @Override
    public double getMetricCountOfReceivedPreferences(MorenoMetricFilterFace _filter, MorenoMeasureFace _measure) {
        double preferencesWeight = 0.0;
        for (MorenoRespondentFace respondent : getModel().getRespondentsList()) {
            for (MorenoAnswerFace answer : respondent.getAnswerList()) {
                if (_filter.hasAnswer(answer)) {
                    for (MorenoAnswerItemFace answerItem : answer.getAnswerItems()) {
                        if (this == answerItem.getTarget()) {
                            preferencesWeight += _measure.getWeight(answerItem.getQuestionItem().getItemNumber());
                        }
                    }
                }
            }
        }
        return preferencesWeight;
    }

    @Override
    public double getMetricCountOfGivenPreferences(MorenoMetricFilterFace _filter, MorenoMeasureFace _measure) {
        double preferencesWeight = 0.0;
        for (MorenoAnswerFace answer : getAnswerList()) {
            if (_filter.hasAnswer(answer)) {
                for (MorenoAnswerItemFace answerItem : answer.getAnswerItems()) {
                    if (answerItem.getTarget() != null) {
                        preferencesWeight += _measure.getWeight(answerItem.getQuestionItem().getItemNumber());
                    }
                }
            }
        }
        return preferencesWeight;
    }

    @Override
    public double getMetricCountOfPreferencesWeighted(MorenoMetricFilterFace _filter) {
        double countOfPreferences = 0.0;
        for (MorenoRespondentFace respondent : getModel().getRespondentsList()) {
            for (MorenoAnswerFace answer : respondent.getAnswerList()) {
                if (_filter.hasAnswer(answer)) {
                    for (MorenoAnswerItemFace answerItem : answer.getAnswerItems()) {
                        if (this == answerItem.getTarget()) {
                            switch (answerItem.getQuestionItem().getItemNumber()) {
                                case 0:
                                    countOfPreferences += 2.0;
                                case 1:
                                    countOfPreferences += 1.0;
                                default:
                                    countOfPreferences += 0.5;
                            }
                        }
                    }
                }
            }
        }
        return countOfPreferences;
    }

    @Override
    public double getMetricCountOfMutualPreference(MorenoMetricFilterFace _filter) {
        double countOfPreferences = 0;
        for (MorenoRespondentFace respondent : getModel().getRespondentsList()) {
            for (MorenoAnswerFace answer : respondent.getAnswerList()) {
                if (_filter.hasAnswer(answer)) {
                    for (MorenoAnswerItemFace answerItem : answer.getAnswerItems()) {
                        if (this == answerItem.getTarget()) {
                            MorenoAnswerFace thisAnswer = this.getAnswerByQuestion(answer.getQuestion());
                            MorenoAnswerItemFace thisAnswerItem = thisAnswer.getAnswerItemByRespondent(respondent);
                            if (thisAnswerItem != null) {
                                countOfPreferences++;
                            }
                        }
                    }
                }
            }
        }
        return countOfPreferences;
    }

    @Override
    public double getMetricIndividualStatus() {
        double measure = getMetricCountOfReceivedPreferences(
                new MorenoMetricFilterFace() {
                    @Override
                    public boolean hasAnswer(MorenoAnswerFace _answer) {
                        return true;
                    }

                    @Override
                    public List getQuestions() {
                        throw new UnsupportedOperationException("Not supported yet.");
                    }

                },
                new MorenoMeasureImpl(2D, 1D, 0.5D));
        if (measure >= 2.0) {
            return 0;
        } else if (measure > 1.0) {
            return 1;
        } else if (measure > 0.5) {
            return 2;
        } else {
            return 3;
        }
    }

    @Override
    public List<MorenoAnswerFace> getAnswerList() {
        return new ArrayList<MorenoAnswerFace>(answersMap.values());
    }

    @Override
    public MorenoAnswerFace getAnswerByQuestion(MorenoQuestionFace _question) {
        if (!answersMap.containsKey(_question)) {
            answersMap.put(_question, new MorenoAnswerImpl(this, _question));
        }
        return answersMap.get(_question);
    }

}
